package charts; 
import charts.series.Element;
import charts.Base;
import string.Utils;
import global.Global;

//class BarBase extends Base { // Break down enslavement by the Base
//class BarBase<StyleType, ValueType> extends Sprite {
class BarBase<StyleType, ValueType> extends Base<ValueType> {
	
	var group:Int;
	var style:StyleType;
	var values:Array<ValueType>; // TODO + figure out the actual type instead of Dynamic => templatized the mother
	var colour:String;
	var key:String;
	var font_size:Float;
	
	public function new( json:Dynamic, group:Float )
	{
		super();
		this.style = {
			values:				[],
			colour:				'#3030d0',
			text:				'',		// <-- default not display a key
			font_size:			12,
			tip:				'#val#<br>#x_label#',
			alpha:				0.6,
			onclick:			null,
			axis:				'left'
		};
		
		Object_helper.merge_2( json, this.style ); // TODO -  figure out why I need this
		
		this.colour	= string.Utils.get_colour( this.style.colour );
		this.key	= this.style.text;
		this.font_size	= this.style.font_size;

		// Minor hack, replace all #key# with this key text:
		this.style.tip =  StringTools.replace(this.style.tip,'#key#', this.key);
		
		//
		// bars are grouped, so 3 bar sets on one chart
		// will arrange them selves next to each other
		// at each value of X, this.group tell the bar
		// where it is in that grouping
		//
		this.group = group;
		
		this.values = this.style.values;
		this.add_values();
	}
	
	
	//
	// hello people in the future! I was doing OK until I found some red wine. Now I can't figure stuff out,
	// like, do I pass in this.axis, or do I make it a member of each PointBarBase? I don't know. Hey, I know
	// I'll flip a coin and see what happens. It was heads. What does it mean? Mmmmm.... red wine....
	// Fuck it, I'm passing it in. Makes the resize method messy, but keeps the PointBarBase clean.
	//
//	public override function resize( sc:ScreenCoordsBase ): Void {
	public function resize( sc:ScreenCoordsBase ): Void {
		
		for ( i in 0...this.numChildren)
		{
			var e:Element = cast( this.getChildAt(i), Element);
			e.resize( sc );
		}
	}
	
	
	public override function get_max_x():Float {
		
		var max_index:Int = Math.NEGATIVE_INFINITY;
		
		for ( i in 0...this.numChildren) {
			
			var e:Element = cast( this.getChildAt(i), Element);
			max_index = Math.max( max_index, e.index );
		}
		
		// 0 is a position, so count it:
		return max_index;
	}
	
	public override function get_min_x():Float {
		return 0;
	}
	
	//
	// override or don't call this if you need better help
	//
	function get_element_helper( value:ValueType ): StyleType {
		
		var default_style:StyleType = {
			colour		: this.style.colour,
			tip		: this.style.tip,
			alpha		: this.style.alpha,
			onclick		: this.style.onclick,
			axis		: this.style.axis
		};
		
		if( Std.is( value, Float) )
			default_style.top = value;
		else
			Object_helper.merge_2( value, default_style ); // TODO - figure out why I need this
			
		// our parent colour is a number, but
		// we may have our own colour:
		if( Std.is( default_style.colour, String) )
			default_style.colour = Utils.get_colour( default_style.colour );
		
		// Tr.ace_json(default_style);
		return default_style;
	}
	
	
	/*
			
		+-----+
		|  B  |
		+-----+     |   +-----+
		|  A  |     |   |  C  +- - -
		|     |     |   |     |  D
		+-----+-----+---+-----+- - -
			1   2
		
	*/
		
	
//	public override function closest( x:Float, y:Float ): Dynamic {
	public function closest( x:Float, y:Float ): ClosestStruct {
		var shortest:Int = Math.INFINITY;
		var ex:Element = null;
		
		for ( i in 0...this.numChildren)
		{
			var e:Element = cast( this.getChildAt(i), Element);

			e.is_tip = false;
			
			if( (x > e.x) && (x < e.x+e.width) )
			{
				// mouse is in position 1
				shortest = Math.min( Math.abs( x - e.x ), Math.abs( x - (e.x+e.width) ) );
				ex = e;
				break;
			}
/*			else
			{*/
				// mouse is in position 2
				// get distance to left side and right side
				var d1:Int = Math.abs( x - e.x );
				var d2:Int = Math.abs( x - (e.x+e.width) );
				var min:Int = Math.min( d1, d2 );
				if( min < shortest )
				{
					shortest = min;
					ex = e;
				}
// 			}
		}
		var dy:Int = Math.abs( y - ex.y );
		
		return { element:ex, distance_x:shortest, distance_y:dy };
	}
}

